package com.atguigu.serviceedu.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.serviceedu.entity.EduSubject;
import com.atguigu.serviceedu.entity.excel.SubjectExcel;
import com.atguigu.serviceedu.entity.vo.OneSubjectVo;
import com.atguigu.serviceedu.entity.vo.TwoSubjectVo;
import com.atguigu.serviceedu.listener.SubjectExcelListener;
import com.atguigu.serviceedu.mapper.EduSubjectMapper;
import com.atguigu.serviceedu.service.EduSubjectService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程科目 服务实现类
 * </p>
 * @author yzh
 * @since 2022-01-09
 */
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {

    @Override
    public void dealWithSubjectExcelData(MultipartFile file, EduSubjectService subjectService) {
        try {
            // 文件输入流
            InputStream inputStream = file.getInputStream();
            // 调用方法进行读取
            EasyExcel.read(inputStream, SubjectExcel.class, new SubjectExcelListener(subjectService)).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<OneSubjectVo> getSubjectTreeList() {
        QueryWrapper oneQueryWrapper = new QueryWrapper();
        oneQueryWrapper.eq("parent_id", "0");
        List<EduSubject> oneSubjectListDb = baseMapper.selectList(oneQueryWrapper);

        QueryWrapper twoQueryWrapper = new QueryWrapper();
        twoQueryWrapper.ne("parent_id", "0");
        List<EduSubject> twoSubjectListDb = baseMapper.selectList(twoQueryWrapper);

        Map<String, List<TwoSubjectVo>> twoSubjectVoListMap = twoSubjectListDb
                .stream().map(twoSubject -> {
                    TwoSubjectVo twoSubjectVo = new TwoSubjectVo();
                    BeanUtils.copyProperties(twoSubject, twoSubjectVo);
                    return twoSubjectVo;
                })
                .collect(Collectors.groupingBy(TwoSubjectVo::getParentId));

        List<OneSubjectVo> resultList = new ArrayList<>();
        oneSubjectListDb.forEach(oneSubject -> {
            OneSubjectVo oneSubjectVo = new OneSubjectVo();
            BeanUtils.copyProperties(oneSubject, oneSubjectVo);

            List<TwoSubjectVo> twoSubjectList = twoSubjectVoListMap.get(oneSubject.getId());
            oneSubjectVo.setChildren(twoSubjectList);

            resultList.add(oneSubjectVo);
        });

        return resultList;
    }

    /**
     * 递归查询
     */
    @Override
    public List<EduSubject> getSubjectTreeListByRecursion() {
        // 1.查询表中所有的数据
        List<EduSubject> allList = baseMapper.selectList(null);

        // 2.找到所有的根节点
        List<EduSubject> rootList = allList.stream()
                .filter(subject -> "0".equals(subject.getParentId()))
                .collect(Collectors.toList());

        // 3.查询所有非根节点
        List<EduSubject> subList = allList.stream()
                .filter(subject -> !"0".equals(subject.getParentId()))
                .collect(Collectors.toList());

        // TODO 2和3步可以用同一个循环解决

        // 4.循环根节点查找对应的子节点
        rootList.forEach(root -> this.findChildrenNode(root, subList));
        return rootList;
    }

    /**
     * 递归查找子节点方法, 参数 一个根节点，所有非根节点集合
     */
    private void findChildrenNode(EduSubject root, List<EduSubject> subList) {
        // 通过根节点id和子节点pid是否相等，如果相等代表当前根的子集
        List<EduSubject> childrenList = subList.stream()
                .filter(subject -> subject.getParentId().equals(root.getId()))
                .collect(Collectors.toList());

        if (!CollectionUtils.isEmpty(childrenList)) {
            // 赋值
            root.setChildren(childrenList);
            // 再次递归查询根节点孩子是否还有孩子
            childrenList.forEach(e -> this.findChildrenNode(e, subList));
        }
    }

    /**
     * 递归查询
     */
    @Override
    public List<EduSubject> getSubjectTreeListByRecursionMap() {
        // 1.查询表中所有的数据
        List<EduSubject> allList = baseMapper.selectList(null);

        List<EduSubject> rootList = new ArrayList();
        List<EduSubject> subList = new ArrayList<>();

        allList.stream().forEach(subject -> {
            if ("0".equals(subject.getParentId())) {
                // 2.找到所有的根节点
                rootList.add(subject);
            } else {
                // 3.查询所有非根节点
                subList.add(subject);
            }
        });

        Map<String, List<EduSubject>> subListMap = subList.stream()
                .collect(Collectors.groupingBy(EduSubject::getParentId));

        // 4.循环根节点查找对应的子节点
        rootList.forEach(root -> this.findChildrenNodeMap(root, subListMap));
        return rootList;
    }

    /**
     * 递归查找子节点方法, 参数 一个根节点，所有非根节点集合
     */
    private void findChildrenNodeMap(EduSubject root, Map<String, List<EduSubject>> subListMap) {
        // 通过根节点id和子节点pid是否相等，如果相等代表当前根的子集
        List<EduSubject> childrenList = subListMap.get(root.getId());

        if (!CollectionUtils.isEmpty(childrenList)) {
            // 赋值
            root.setChildren(childrenList);
            // 再次递归查询根节点孩子是否还有孩子
            childrenList.forEach(e -> this.findChildrenNodeMap(e, subListMap));
        }
    }

}
